package dao

import (
	"bookmark-web/utils"
	"fmt"
	"os"
	"strings"
	"time"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"

	"bookmark-web/models"
)

// 全局数据库连接变量
var DB *gorm.DB

// 包级变量，首字母大写，对外可见。即，在 dao 包下的所有文件都可以直接访问，其它包可导入此包后访问

// 从环境变量获取数据库配置，默认值为开发环境配置
func getEnv(key, defaultValue string) string {
	value, exists := os.LookupEnv(key)
	if exists {
		return value
	}
	return defaultValue
}

// 数据库配置
var (
	UserName = getEnv("MYSQL_USER", "root")        // 数据库用户名
	Password = getEnv("MYSQL_PASSWORD", "123")     // 数据库密码
	Host     = getEnv("MYSQL_HOST", "127.0.0.1")   // 数据库地址
	Port     = getEnv("MYSQL_PORT", "3306")        // 数据库端口
	DBName   = getEnv("MYSQL_DATABASE", "website") // 数据库名 (匹配database.sql中的数据库名)
)

// 创建数据库。如果数据库不存在则创建数据库
func createDatabase() error {
	// 连接 MySQL 数据库
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/?charset=utf8mb4&parseTime=True&loc=Local",
		UserName, Password, Host, Port)
	db, err := gorm.Open(mysql.New(mysql.Config{
		DSN:                       dsn,
		DefaultStringSize:         256,   // string 类型字段的默认长度
		SkipInitializeWithVersion: false, // 根据当前 MySQL 版本自动配置
	}), &gorm.Config{})
	if err != nil {
		return fmt.Errorf("连接数据库失败: %v", err)
	}
	// 执行创建数据库的 SQL 语句
	createDBQuery := fmt.Sprintf("CREATE DATABASE IF NOT EXISTS `%s` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci", DBName)
	err = db.Exec(createDBQuery).Error
	if err != nil {
		return fmt.Errorf("创建数据库失败: %v", err)
	}
	fmt.Printf("数据库 %s 创建成功\n", DBName)
	//log.Default().Println("数据库 %s 创建成功\n", DBName)
	return nil
}

// InitDB 初始化数据库连接
func InitDB() error {
	// 构建数据库连接字符串
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
		UserName, Password, Host, Port, DBName)

	// 连接数据库
	var err error
	DB, err = gorm.Open(mysql.New(mysql.Config{
		DSN:                       dsn,
		DefaultStringSize:         256,   // string 类型字段的默认长度
		SkipInitializeWithVersion: false, // 根据当前 MySQL 版本自动配置
	}), &gorm.Config{})
	if err != nil {
		// 检查是否是数据库不存在异常
		if strings.Contains(err.Error(), "Unknown database") {
			// 是，则创建数据库
			err = createDatabase()
			if err != nil {
				return fmt.Errorf("创建数据库失败: %v", err)
			}
			// 重新连接数据库
			DB, err = gorm.Open(mysql.New(mysql.Config{
				DSN:                       dsn,
				DefaultStringSize:         256,   // string 类型字段的默认长度
				SkipInitializeWithVersion: false, // 根据当前 MySQL 版本自动配置
			}), &gorm.Config{})
			if err != nil {
				return fmt.Errorf("重新连接数据库失败: %v", err)
			}
		} else {
			// 不是，则抛出异常
			return fmt.Errorf("连接数据库失败: %v", err)
		}
	}

	// 配置连接池
	sqlDB, err := DB.DB()
	if err != nil {
		return fmt.Errorf("获取数据库连接池失败: %v", err)
	}

	// 设置连接池参数
	sqlDB.SetConnMaxLifetime(time.Minute * 10) // 连接的最大生命周期
	sqlDB.SetMaxOpenConns(50)                  // 最大打开连接数
	sqlDB.SetMaxIdleConns(15)                  // 最大空闲连接数

	// 自动迁移创建所有表
	err = DB.AutoMigrate(
		&models.User{},
		&models.Category{},
		&models.Bookmark{},
	)
	if err != nil {
		return fmt.Errorf("创建数据表失败: %v", err)
	}
	// 向数据库插入初始数据。用户表，admin、123456789
	err = InsertInitialData()
	if err != nil {
		return fmt.Errorf("插入初始数据失败: %v", err)
	}

	return nil
}

// InsertInitialData 向数据库插入初始数据
func InsertInitialData() error {
	// 检查是否已存在管理员用户
	var user models.User
	result := DB.Where("username = ?", "admin").First(&user)

	// 如果没有找到管理员用户，则创建初始数据
	if result.Error != nil {
		// 创建管理员用户
		hashedPassword, err := utils.HashPassword("123456789")
		if err != nil {
			return fmt.Errorf("密码加密失败")
		}
		adminUser := models.User{
			Username: "admin",
			Password: hashedPassword,
			Email:    "admin@example.com",
			IsAdmin:  true,
		}

		// 插入管理员用户
		if err := DB.Create(&adminUser).Error; err != nil {
			return fmt.Errorf("创建管理员用户失败: %v", err)
		}

		fmt.Println("初始数据插入成功")
	} else {
		fmt.Println("管理员用户已存在，跳过初始数据插入")
	}

	return nil
}

// GetDB 获取数据库连接
func GetDB() *gorm.DB {
	return DB
}
